from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError


# 审批流类
class Workflow(models.Model):
    _name = 'sb.workflow'
    _description = 'Approval Workflow Class'
    _inherit = ['mail.thread', 'mail.activity.mixin']

    name = fields.Char(string="Name")
    state = fields.Selection([
        ('approval', 'Under Approval'),
        ('approve', 'Approved'),
        ('fail_to_approve', 'Failed to Approve'),
    ], default="approval", compute="_compute_state", string="Status", store=True)
    approval_time = fields.Datetime(string="Approval Submission Time")
    workflow_type = fields.Selection([
        ('account_in', 'purchase invoice'),
        ('other', 'Other')
    ], string="Approval Category")
    # Approval Items
    sb_workflow_item_ids = fields.One2many('sb.workflow.item', 'sb_workflow_id', string="Approval Items")
    # Attachments
    sb_workflow_attachments_ids = fields.One2many('sb.workflow.attachments', 'sb_workflow_id',
                                                  string="Approval Attachments")
    active = fields.Boolean(string="Active", default=True)
    product_id = fields.Many2one('product.product', readonly=True, copy=False)
    qty = fields.Integer('quantity', readonly=True, copy=False)
    remark = fields.Text(string="Remark")
    workflow_data = fields.Json(string="Approval Data")
    res_model = fields.Char(string='Related Model', readonly=True)
    res_id = fields.Integer(string='Related Record ID', readonly=True)
    document_ids = fields.Many2many('ir.attachment', string="Related Documents", compute='_compute_document_ids')

    @api.depends('res_model', 'res_id')
    def _compute_document_ids(self):
        for rec in self:
            if rec.res_model and rec.res_id:
                rec.document_ids = [(6, 0, self.env['ir.attachment'].search([
                    ('res_model', '=', rec.res_model),
                    ('res_id', '=', rec.res_id)
                ]).ids)]
            else:
                rec.document_ids = [(5, 0, 0)]

    # 获取审批流状态
    @api.depends('sb_workflow_item_ids', 'sb_workflow_item_ids.state')
    def _compute_state(self):
        for workflow in self:
            w_item_states = []
            # 获取全部审批项状态
            for w_item in workflow.sb_workflow_item_ids:
                w_item_states.append(w_item.state)
            # 判断
            if 'no_pass' in w_item_states:
                workflow.state = 'fail_to_approve'
            elif 'approval' in w_item_states or 'wait_forward' in w_item_states:
                workflow.state = 'approval'
            else:
                workflow.state = 'approve'


# 审批流审批项
class WorkflowItem(models.Model):
    _name = 'sb.workflow.item'
    _description = 'Approval Workflow Approval Item'
    _order = 'audit_level,state desc'

    name = fields.Char(string="Name")
    state = fields.Selection([
        ('wait_forward', 'Waiting for Pre-approval'),
        ('approval', 'Under Approval'),
        ('pass', 'Passed'),
        ('no_pass', 'Not Passed'),
    ], string="Status")
    approval_time = fields.Datetime(string="Approval Time")
    user_group_ids = fields.Many2many('res.users', string="Approvers")
    user_id = fields.Many2one('res.users', string="Approver")
    active_user = fields.Many2one('res.users', string="Active User", compute='_get_active_user')
    approval_instructions = fields.Text(string="Approval Instructions")
    # Whether approval can be performed
    is_approval = fields.Boolean(string="Can Perform Approval", compute="_compute_is_approval")
    # Approval Level
    audit_level = fields.Integer(default=1, string="Approval Level")
    # 审批流
    sb_workflow_id = fields.Many2one('sb.workflow', ondelete="cascade")
    # 审批流状态
    sb_workflow_id_state = fields.Selection(related="sb_workflow_id.state", readonly=True)
    workflow_type = fields.Selection(related="sb_workflow_id.workflow_type")
    is_plan = fields.Boolean(string='Plan or not', default=False)
    active = fields.Boolean(string="Active", related='sb_workflow_id.active', store=True)
    remark = fields.Text(string="Remark", related='sb_workflow_id.remark')
    # 提交人
    submitter_id = fields.Many2one('res.users', related="sb_workflow_id.create_uid", string="Submitter")
    # 提交时间
    submission_time = fields.Datetime(related="sb_workflow_id.approval_time", string="Submission time")

    @api.depends()
    def _get_active_user(self):
        for item in self:
            item.active_user = self.env.user.id

    # 是否能进行审批
    @api.depends('user_group_ids')
    def _compute_is_approval(self):
        for workflow_item in self:
            if self.env.user.id in workflow_item.user_group_ids.ids:
                workflow_item.is_approval = True
            else:
                workflow_item.is_approval = False

    def review(self):
        context = {
            'sb_workflow_item_id': self.id,
            'workflow_type': self.sb_workflow_id.workflow_type,
            'is_plan': self.is_plan,
        }
        return {
            'name': 'Undergoing Approval',
            'type': 'ir.actions.act_window',
            'res_model': 'workflow.check.wizard',
            'view_mode': 'form',
            # 'res_id': self.id,
            # 'views': [(self.env.ref('').id, 'form')],
            'target': 'new',
            'context': context,
        }

    def through(self):

        workflow_check_w_id = self.env['workflow.check.wizard'].new({
            'sb_workflow_item_id': self.id,
        })
        if workflow_check_w_id:
            workflow_check_w_id.approval_pass()
        # self.write({
        #     'state': 'pass',
        #     'approval_time': fields.Datetime.now(),
        #     'user_id': self.env.user.id,
        #     'approval_instructions': '通过'
        # })
        # # 进行中的同层级：
        # tong_item_ids = self.env['sb.workflow.item'].search(
        #     [('sb_workflow_id', '=', self.sb_workflow_id.id),
        #      ('audit_level', '=', self.audit_level),
        #      ('state', '=', 'approval')])
        # if not tong_item_ids:
        #     # 如有层级审核开放下一层级审核
        #     sb_workflow_id = self.sb_workflow_id
        #     # 该审核所有审核流层级
        #     workflow_level_ids = []
        #     for workflow_item in sb_workflow_id.sb_workflow_item_ids:
        #         workflow_level_ids.append(workflow_item.audit_level)
        #     # 去重排序
        #     qc_workflow_level_ids = list(set(workflow_level_ids))
        #     qc_workflow_level_ids.sort()
        #     # 开放一下层级
        #     index = qc_workflow_level_ids.index(self.audit_level)
        #     if index + 1 < len(qc_workflow_level_ids):
        #         next_audit_level = qc_workflow_level_ids[index + 1]
        #         for item in sb_workflow_id.sb_workflow_item_ids:
        #             if item.audit_level == next_audit_level and item.state == 'wait_forward':
        #                 item.state = 'approval'

    # 审核通过
    def approval_pass(self):
        self.ensure_one()
        if self.state == 'approval':
            self.write({
                'state': 'pass',
                'approval_time': fields.Datetime.now(),
                'user_id': self.env.user.id,
                'approval_instructions': self.approval_instructions or '通过'
            })
            # 进行中的同层级：
            tong_item_ids = self.env['sb.workflow.item'].search([
                ('sb_workflow_id', '=', self.sb_workflow_id.id),
                 ('audit_level', '=', self.audit_level),
                 ('state', '=', 'approval')
            ])
            if not tong_item_ids:
                # 如有层级审核开放下一层级审核
                sb_workflow_id = self.sb_workflow_id
                # 该审核所有审核流层级
                workflow_level_ids = []
                for workflow_item in sb_workflow_id.sb_workflow_item_ids:
                    workflow_level_ids.append(workflow_item.audit_level)
                # 去重排序
                qc_workflow_level_ids = list(set(workflow_level_ids))
                qc_workflow_level_ids.sort()
                # 开放一下层级
                index = qc_workflow_level_ids.index(self.audit_level)
                if index + 1 < len(qc_workflow_level_ids):
                    next_audit_level = qc_workflow_level_ids[index + 1]
                    for item in sb_workflow_id.sb_workflow_item_ids:
                        if item.audit_level == next_audit_level and item.state == 'wait_forward':
                            item.state = 'approval'

    def refuse(self):
        self.write({
            'state': 'no_pass',
            'approval_time': fields.Datetime.now(),
            'user_id': self.env.user.id,
            'approval_instructions': '拒绝'
        })

    def skip_view(self):
        return {
            'name': 'Approval Workflow',
            'type': 'ir.actions.act_window',
            'res_model': 'sb.workflow',
            'view_mode': 'form',
            'res_id': self.sb_workflow_id.id,
            # 'views': [(self.env.ref('').id, 'form')],
            'target': 'current',
        }

    def returns(self):
        """审批退回,仅退回上一级"""
        self.ensure_one()
        sb_workflow_item_ids = self.sb_workflow_id.sb_workflow_item_ids.filtered(
            lambda x: x.audit_level < self.audit_level)
        if not sb_workflow_item_ids:
            return
        if len(sb_workflow_item_ids) <= 1:
            sb_workflow_item_ids.write({'state': 'approval',
                                        'user_id': False,
                                        'approval_time': False,
                                        'approval_instructions': False})
            self.write({'state': 'wait_forward',
                        'user_id': self.env.user.id,
                        'approval_time': fields.Datetime.now(),
                        'approval_instructions': '审批退回'})
        else:
            # 获取明细最大的, 置为审批中
            sb_workflow_item_id = sb_workflow_item_ids.sorted(key=lambda x: x.audit_level, reverse=True)[0]
            sb_workflow_item_id.write({
                'state': 'approval',
                'user_id': False,
                'approval_time': False,
                'approval_instructions': False})
            self.write({
                'state': 'wait_forward',
                'user_id': self.env.user.id,
                'approval_time': fields.Datetime.now(),
                'approval_instructions': '审批退回'})


# 审批流审批项
class WorkflowAttachments(models.Model):
    _name = 'sb.workflow.attachments'
    _description = 'Approval Workflow Attachment'

    workflow_attachments_filename = fields.Char(string="Attachment Name")
    workflow_attachments_file = fields.Binary(
        attachment=True,
        string="Attachment File",
    )
    # 审批流
    sb_workflow_id = fields.Many2one('sb.workflow', ondelete="cascade")
